#include "RingQueue.hpp"
#include "Task.hpp"
#include <unistd.h>
#include <ctime>
#include <string>
using namespace std;

struct ThreadData
{
    RingQueue<Task> *rq;
    string threadname;
};

// 消费者
void *Consumer(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);
    RingQueue<Task> *rq = td->rq;
    string name = td->threadname;

    while (true)
    {
        // 1. 消费数据
        Task t;

        rq->Pop(&t);
        // 2. 处理数据
        t.GetRusult();
        cout << "我是消费者, 我获取的任务是: " << t.GetTask()
             << " who: " << name
             << " 结果是: " << t.GetRusult() << endl;
        sleep(1);
    }
}

// 生产者
void *Producter(void *args)
{
    int len = oper.size();
    ThreadData *td = static_cast<ThreadData *>(args);
    RingQueue<Task> *rq = td->rq;
    string name = td->threadname;
    while (true)
    {
        // 1. 获取数据
        int data1 = rand() % 10 + 1;
        usleep(10);
        int data2 = rand() % 10 + 1;
        char op = oper[rand() % len];
        Task t(data1, data2, op);
        // 2. 生产数据
        rq->push(t);
        cout << "我是生产者，我生产的任务是: " << t.GetTask() << " who: " << name << endl;
        // sleep(1);
    }
    return 0;
}

// ========================== 多生产多消费模型 类类型 =======================
int main()
{
    // 随机数种子
    srand(time(nullptr));
    // 阻塞队列
    RingQueue<Task> *rq = new RingQueue<Task>();

    // c - 消费者线程
    // p - 生产者线程
    pthread_t c[5], p[3]; // 5个消费者 3个生产者
    for (int i = 0; i < 3; i++)
    {
        ThreadData *td = new ThreadData;
        td->rq = rq;
        td->threadname = "Productor-" + to_string(i);
        // 生产者线程和消费者线程需要看到同一个环形队列
        pthread_create(p + i, nullptr, Producter, (void *)td);
    }
    for (int i = 0; i < 5; i++)
    {
        ThreadData *td = new ThreadData;
        td->rq = rq;
        td->threadname = "Consumer-" + to_string(i);

        pthread_create(c + i, nullptr, Consumer, (void *)td);
    }

    // 主线程负责等待cp线程

    for (int i = 0; i < 3; i++)
    {
        pthread_join(p[i], nullptr);
    }
    for (int i = 0; i < 5; i++)
    {
        pthread_join(c[i], nullptr);
    }
    return 0;
}

// #include "RingQueue.hpp"
// #include <unistd.h>
// #include <ctime>
// #include <string>
// using namespace std;

// struct ThreadData
// {
//     RingQueue<int> *rq;
//     string threadname;
// };

// // 消费者
// void *Consumer(void *args)
// {
//     ThreadData *td = static_cast<ThreadData *>(args);
//     RingQueue<int> *rq = td->rq;
//     string name = td->threadname;

//     while (true)
//     {
//         // 1. 消费数据
//         int data = 0;
//         rq->Pop(&data);
//         // 2. 处理数据
//         cout << "我是消费者, 我消费的数据是: " << data << " who: " << name << endl;
//         sleep(1);
//     }
// }

// // 生产者
// void *Producter(void *args)
// {
//     ThreadData *td = static_cast<ThreadData *>(args);
//     RingQueue<int> *rq = td->rq;
//     string name = td->threadname;
//     while (true)
//     {
//         // 1. 获取数据
//         int data = rand() % 10 + 1;
//         // 2. 生产数据
//         rq->push(data);
//         cout << "我是生产者，我生产的数据是: " << data << " who: " << name << endl;
//         // sleep(1);
//     }
//     return 0;
// }

// // ========================== 多生产多消费模型 =======================
// int main()
// {
//     // 随机数种子
//     srand(time(nullptr));
//     // 阻塞队列
//     RingQueue<int> *rq = new RingQueue<int>();

//     // c - 消费者线程
//     // p - 生产者线程
//     pthread_t c[5], p[3]; // 5个消费者 3个生产者
//     for (int i = 0; i < 3; i++)
//     {
//         ThreadData *td = new ThreadData;
//         td->rq = rq;
//         td->threadname = "Productor-" + to_string(i);
//         // 生产者线程和消费者线程需要看到同一个环形队列
//         pthread_create(p + i, nullptr, Producter, (void *)td);
//     }
//     for (int i = 0; i < 5; i++)
//     {
//         ThreadData *td = new ThreadData;
//         td->rq = rq;
//         td->threadname = "Consumer-" + to_string(i);

//         pthread_create(c + i, nullptr, Consumer, (void *)td);
//     }

//     // 主线程负责等待cp线程

//     for (int i = 0; i < 3; i++)
//     {
//         pthread_join(p[i], nullptr);
//     }
//     for (int i = 0; i < 5; i++)
//     {
//         pthread_join(c[i], nullptr);
//     }
//     return 0;
// }

// #include "RingQueue.hpp"
// #include <unistd.h>
// #include <ctime>
// using namespace std;

// // 消费者
// void *Consumer(void *args)
// {
//     RingQueue<int> *rq = static_cast<RingQueue<int> *>(args);
//     while (true)
//     {
//         // 1. 消费数据
//         int data = 0;
//         rq->Pop(&data);
//         // 2. 处理数据
//         cout << "我是消费者, 我消费的数据是: " << data << endl;
//         sleep(1);
//     }
// }

// // 生产者
// void *Producter(void *args)
// {
//     // 生产者休眠3秒，观察是否会出现同步现象
//     sleep(3);
//     RingQueue<int> *rq = static_cast<RingQueue<int> *>(args);
//     int data = 0;
//     while (true)
//     {
//         // 1. 获取数据
//         int data = rand() % 10 + 1;
//         // 2. 生产数据
//         rq->push(data);
//         cout << "我是生产者，我生产的数据是: " << data << endl;
//         sleep(1);
//     }
//     return 0;
// }

// // ======================== 单生产单消费模型 =====================================
// int main()
// {
//     // 随机数种子
//     srand(time(nullptr));
//     // 阻塞队列
//     RingQueue<int> *rq = new RingQueue<int>();

//     // c - 消费者线程
//     // p - 生产者线程
//     pthread_t c, p;
//     // 生产者线程和消费者线程需要看到同一个环形队列
//     pthread_create(&c, nullptr, Consumer, (void *)rq);
//     pthread_create(&p, nullptr, Producter, (void *)rq);

//     // 主线程负责等待cp线程
//     pthread_join(c, nullptr);
//     pthread_join(p, nullptr);

//     return 0;
// }

// #include "BlockQueue.hpp"
// #include <unistd.h>
// #include "Task.hpp"
// #include <ctime>

// // 消费者
// void *Consumer(void *args)
// {
//     BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
//     while (true)
//     {
//         // 消费者每隔一秒消费一次
//         // sleep(1);
//         // 消费行为 - 将数据放到阻塞队列里
//         Task t = bq->pop();
//         // 计算
//         t.run();
//         std::cout << "处理任务：" << t.GetTask() << " 运算结果是: " << t.GetRusult() << std::endl;
//         std::cout << "------------------------" << std::endl;
//     }
// }

// // 生产者
// void *Producter(void *args)
// {
//     int len = oper.size();
//     BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
//     int data = 0;
//     while (true)
//     {
//         // 生产行为 - 获取阻塞队列的数据
//         int data1 = rand() % 10 + 1; // 数据范围[1, 10]
//         int data2 = rand() % 10 + 1;
//         char op = oper[rand() % len];
//         Task t(data1, data2, op);
//         usleep(10); // 模拟生产者获取数据。休眠10微秒，即0.00001秒

//         // 生产者每隔一秒生产一次
//         sleep(1);
//         bq->push(t);
//         std::cout << "生产了一个任务: " << t.GetTask() << std::endl;
//         std::cout << "------------------------" << std::endl;
//     }
// }